﻿using DBUtil.FastEntity.Interface;
using DBUtil.Provider.SqlServer;
using DotNetCommon.Data;
using DotNetCommon.Extensions;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace DBUtil.FastEntity.Builders
{
    public class SelectBuilder<T> : ISelectClause<T> where T : class, new()
    {
        private readonly IEntityUtil<T> entityUtil;
        private Type EntityType = null;
        internal DBAccess db = null;

        private List<(string type, object data)> _commands = new List<(string type, object data)>();

        internal List<(string type, object data)> Commands => _commands;

        public SelectBuilder(IEntityUtil<T> entityUtil)
        {
            EntityType = typeof(T);
            this.entityUtil = entityUtil;
            this.db = entityUtil.Db;
        }

        #region 构造

        #region 过滤
        /// <summary>
        /// 过滤条件
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public ISelectClause<T> Where(Expression<Func<T, bool>> expression)
        {
            _commands.Add(("Where", expression));
            return this;
        }

        /// <summary>
        /// 根据主键过滤
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public ISelectClause<T> WhereKey(params int[] key)
        {
            _commands.Add(("WhereKey.int[]", key));
            return this;
        }

        /// <summary>
        /// 根据主键过滤
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public ISelectClause<T> WhereKey(params long[] key)
        {
            _commands.Add(("WhereKey.long[]", key));
            return this;
        }

        /// <summary>
        /// 根据主键过滤
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public ISelectClause<T> WhereKey(params string[] key)
        {
            _commands.Add(("WhereKey.string[]", key));
            return this;
        }
        #endregion

        #region 分页排序
        /// <summary>
        /// 排序
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public ISelectClause<T> OrderBy(Expression<Func<T, object>> expression)
        {
            _commands.Add(("OrderBy", expression));
            return this;
        }

        /// <summary>
        /// 排序(倒序)
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public ISelectClause<T> OrderByDesc(Expression<Func<T, object>> expression)
        {
            _commands.Add(("OrderByDesc", expression));
            return this;
        }
        #endregion

        #region 引入关联字段和关联表

        /// <summary>
        /// 指定一个或多个扩展列<para></para>
        /// <code>
        /// 示例：<br />
        /// <para>.IncludeExtendColumn(t => t.Column1)</para>
        /// .IncludeExtendColumn(t => new { t.Column1,t.Column2 })
        /// </code>
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public ISelectClause<T> IncludeExtendColumn(Expression<Func<T, object>> expression)
        {
            _commands.Add(("IncludeExtendColumn", expression));
            return this;
        }

        /// <summary>
        /// 指定一个或多个扩展列<para></para>
        /// <code>
        /// 示例：<br />
        /// <para>.IncludeExtendColumn(t => t.Table1)</para>
        /// .IncludeExtendColumn(t => new { t.Table1,t.Table1 })
        /// </code>
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public ISelectClause<T> IncludeExtendTable(Expression<Func<T, object>> expression)
        {
            _commands.Add(("IncludeExtendTable", expression));
            return this;
        }

        #endregion

        #endregion

        #region 执行

        private (string sql, IDataParameter[] paras) Generate()
        {
            IDataParameter[] parameters = null;
            var helper = new BuilderHelper<T>(this);
            var tableName = helper.GetTableName();
            var (table, schema) = entityUtil.Db.Manage.PureName(tableName);
            var from = $"from [{schema}].[{table}]";
            var keyMetas = helper.GetKeys();
            var select = "";
            var where = new List<string>();
            for (int i = 0; i < _commands.Count; i++)
            {
                var cmd = _commands[i];
                if (cmd.type.StartsWith("Where"))
                {
                    //过滤条件
                    if (cmd.type == "WhereKey.int[]" || cmd.type == "WhereKey.long[]")
                    {
                        // int/long主键
                        long[] keys = null;
                        if (cmd.type == "WhereKey.int[]")
                        {
                            var _tmp = cmd.data as int[];
                            keys = _tmp.ToList().Select(k => (long)k).ToArray();
                        }
                        else
                        {
                            keys = cmd.data as long[];
                        }
                        if (keyMetas.Count != 1) throw new Exception("主键个数不正确!");
                        var key = keyMetas.FirstOrDefault();
                        if (keys.Length == 1)
                        {
                            where.Add($"({key.name}='{keys[0]}')");
                        }
                        else if (keys.Length > 1)
                        {
                            where.Add($"({key.name} in ({string.Join(",", keys)}))");
                        }
                    }
                    else if (cmd.type == "WhereKey.string[]")
                    {
                        //string主键
                        var keys = cmd.data as object[];
                        keys = keys.ToList().Select(k => k.ToString().Replace("'", "''")).ToArray();
                        if (keyMetas.Count != 1) throw new Exception("主键个数不正确!");
                        var key = keyMetas.FirstOrDefault();
                        if (keys.Length == 1)
                        {
                            where.Add($"({key.name}='{keys[0]}')");
                        }
                        else if (keys.Length > 1)
                        {
                            where.Add($"({key.name} in ({string.Join(",", keys)}))");
                        }
                    }
                    else
                    {
                        //where条件
                        var exp = cmd.data as LambdaExpression;
                        var (filter, paras) = helper.ParseLamda(exp);
                        parameters.AddRange(paras);
                        where.Add(filter);
                    }
                }
                else
                {

                }
            }
            if (select.IsNullOrEmptyOrWhiteSpace())
            {
                select = "select * ";
            }
            var whereStr = string.Join("and", where);
            if (!whereStr.IsNullOrEmptyOrWhiteSpace()) whereStr = $"where {whereStr}";
            var sql = $"{select} {from} {whereStr}";
            return (sql, parameters);
        }

        /// <summary>
        /// 返回查到的第一个对象,如果没查到就返回null
        /// </summary>
        /// <returns></returns>
        public T FirstOrDefault()
        {
            var (sql, paras) = Generate();
            return db.SelectModel<T>(sql, paras);
        }

        /// <summary>
        /// 返回查询到的结果
        /// </summary>
        /// <returns></returns>
        public List<T> ToList()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 返回生成的Sql
        /// </summary>
        /// <returns></returns>
        public string ToSql()
        {
            var (sql, paras) = Generate();
            return sql;
        }

        /// <summary>
        /// 返回生成的Sql和参数化数组
        /// </summary>
        /// <returns></returns>
        public (string sql, IDataParameter[] paras) ToSqlWithParas()
        {
            return Generate();
        }

        /// <summary>
        /// 执行查询,返回分页数据
        /// </summary>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public Page<T> ToPage(int pageIndex = 1, int pageSize = 10)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 执行查询，返回记录数
        /// </summary>
        /// <returns></returns>
        public long Count()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 获取单列和
        /// </summary>
        /// <typeparam name="TProp"></typeparam>
        /// <param name="expression"></param>
        /// <returns></returns>
        public TProp Sum<TProp>(Expression<Func<T, TProp>> expression)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 获取单列最大值
        /// </summary>
        /// <typeparam name="TProp"></typeparam>
        /// <param name="expression"></param>
        /// <returns></returns>
        public TProp Max<TProp>(Expression<Func<T, TProp>> expression)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 获取单列最小值
        /// </summary>
        /// <typeparam name="TProp"></typeparam>
        /// <param name="expression"></param>
        /// <returns></returns>
        public TProp Min<TProp>(Expression<Func<T, TProp>> expression)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 获取单列平均值
        /// </summary>
        /// <typeparam name="TProp"></typeparam>
        /// <param name="expression"></param>
        /// <returns></returns>
        public TProp Avg<TProp>(Expression<Func<T, TProp>> expression)
        {
            throw new NotImplementedException();
        }
        #endregion
    }
}
